﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;

namespace VDataAdapter.WorkerManagement
{
    /// <summary>
    /// Handle transactions receiving event:
    /// Transations are split and sent in mutiple times
    /// </summary>
    class TransactionBuffer  
    {
        public TransactionBuffer()
        {
        }

        private List<PriceLibrary.ChartService.Transaction> _transactions;

        /// <summary>
        /// Sort transactions in Time Order
        /// </summary>
        /// <param name="transactions"></param>
        /// <returns></returns>
        private IList<PriceLibrary.ChartService.Transaction> SortByTime(IList<PriceLibrary.ChartService.Transaction> transactions)
        {
            throw new NotImplementedException();
        }

        private void AddToTransactions(IList<PriceLibrary.ChartService.Transaction> transactions)
        {
            if(_transactions == null)
                throw new NullReferenceException("Transaction List is not initialized yet");
            
            foreach(PriceLibrary.ChartService.Transaction trans in transactions)
            {
                _transactions.Add(trans);
            }
        }

        private List<int> _countHistories = new List<int>();

        /// <summary>
        /// Received transacstion and add to its own list
        /// </summary>
        /// <param name="transactions"></param>
        /// <param name="currentCount"></param>
        /// <param name="totalCount"></param>
        public bool ReceivedTransaction(IList<PriceLibrary.ChartService.Transaction> transactions, int currentCount, int totalCount)
        {          
            if(currentCount == 1)
                _transactions = new List<PriceLibrary.ChartService.Transaction>();
            else
                CheckCountExisted(currentCount, _countHistories);
            
            _countHistories.Add(currentCount);

            AddToTransactions(transactions);

            if (IsReceivedAll(currentCount, totalCount))
            {
                if (!HasAllCount(_countHistories, totalCount))
                    return false;
                
                _transactions = SortTransactionList(_transactions);
                
                return true;
            }

            return false;
        }

        private bool CheckCountExisted(int count, List<int> list)
        {
            if (list.Contains(count))
                throw new Exception("Count already existed");

            return false;
        }

        public List<PriceLibrary.ChartService.Transaction> Transactions
        {
            get {return _transactions;}
        }

        public int TransactionCount()
        {
            if (_transactions != null)
                return _transactions.Count;
            else
                throw new NullReferenceException();
        }

        private List<PriceLibrary.ChartService.Transaction> SortTransactionList(List<PriceLibrary.ChartService.Transaction> transactions)
        {    
            return transactions.Distinct().OrderBy(c => int.Parse(c.Time)).ToList();
        }

        /// <summary>
        /// Only return true if in the list there are 'totalCount' of distinct item
        /// </summary>
        /// <param name="counts"></param>
        /// <param name="totalCount"></param>
        /// <returns></returns>
        private bool HasAllCount(List<int> counts, int totalCount)
        {
            if (counts.Count != totalCount) return false;

            List<int> trackDuplicate = new List<int>();
            foreach (int item in counts)
            {
                if (!trackDuplicate.Contains(item))
                    trackDuplicate.Add(item);
                else
                    return false;
            }
            return true;
        }

        private bool IsReceivedAll(int currentCount, int totalCount)
        {
            if (currentCount == totalCount)
                return true;

            return false;
        }

 

    }
}
